#groovy #gpath

#### Запуск файлов Groovy в Idea

Подключить зависимость для запуска groovy файлов:
```
<dependency>
    <groupId>org.apache.groovy</groupId>
    <artifactId>groovy</artifactId>
    <version>${version}</version>
</dependency>
```

### Работа с Map

#### Создание пустого объекта Map
```groovy
  def map = [:]
  println map
    // Output: [:]
```

#### Создание объекта Map
```groovy
  def map = [name:"Jerry", age:42, city:"New York"]
  println map
    // Output: [name:Jerry, age:42, city:New York]
```

#### Добавление элемента
```groovy
  def map = [:]
// Добавление элемента возможно двумя путями:
// - Java-подобным способом:
  map["age"] = 42
  println map
    // Output: [age:42]
// - по ключу через точку:
  map.age = 42
  println map
    // Output: [age:42]
```

#### Использование имени как ключа
```groovy
  def hobbyLiteral = "hobby"
  def hobbyMap = [(hobbyLiteral):"Singing"]
  def map = [:]
  map.putAll(hobbyMap)
  println map
    // Output: [hobby:Singing]
```

#### Внутренняя переменная it для обхода элементов Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
// Во всех методах при работе с Map используется внутренняя переменная it
// Следующие записи эквивалентны:
  map.each{it -> print it.key + ","}
    // Output: 1,a,2,4,ba,6,7,
  map.each{print it.key + ","}
    // Output: 1,a,2,4,ba,6,7,
// По умолчанию внутренню переменную it не требуется объявлять, но если необходимо изменить ее имя
// это производится с ее обхявлением:
  map.each{elem -> print elem.key + ", "}
    // Output: 1,a,2,4,ba,6,7,
```

#### Удаление элементов с сохранением исходной Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34]
  def minusMap = map.minus([2:42, 4:34]);
  println map
    // Output: [1:20, a:30, 2:42, 4:34]
  println minusMap
    // Output: [1:20, a:30]
```

#### Удаление элементов с преобразованием исходной Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
  map.removeAll{it -> it.key instanceof String}
  println map
    // Output: [1:20, 2:42, 4:34, 6:39, 7:49]
```

#### TODO Дополнить описание метода retainAll
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
  map.retainAll{it -> it.value > 30}
  println map
    // Output: [2:42, 4:34, ba:67, 6:39, 7:49]
```

#### Обход элементов Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34]
// Реализация через объявленный итератор:
  map.each{entry -> print "$entry.key:$entry.value | "}
    // Output: 1:20 | a:30 | 2:42 | 4:34 | 
// Аналогичная команда с реализацией через внутренний итератор:
  map.each{print "$it.key:$it.value | "}
    // Output: 1:20 | a:30 | 2:42 | 4:34 | 
```

#### Перебор элементов Map с индексом
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
  map.eachWithIndex{entry, i -> print "$i $entry.key:$entry.value | "}
    // Output: 0 2:42 | 1 4:34 | 2 ba:67 | 3 6:39 | 4 7:49 | 
  map.eachWithIndex{key, value, i -> print "$i $key:$value | "} 
    // Output: 0 2:42 | 1 4:34 | 2 ba:67 | 3 6:39 | 4 7:49 | 
```

#### Получение ключа и значения
```groovy
  def map = [name:"Jerry", age:42, city:"New York"]
// Получение ключа и значения возможно двумя способами:
// - Java-подобным способом:
  println map.find{it.getKey() == 'age'}.getValue()
    // Output: 42
// - в упрощенном виде:
  println map.find{it.key == 'age'}.value
    // Output: 42
```

#### Поиск первого элемента, совпадающего с условием
```groovy
  def map = [name:"Jerry", age:42, city:"New York", hobby:"Singing"]
  println map.find{it.value == "New York"}.key == "city"
    // Output: true
```

#### Поиск всех элементов, совпадающих с условием
```groovy
  def map = [name:"Jerry", age:42, city:"New York", hobby:"Singing"]
  println map.findAll{it.value == "New York"} == [city:"New York"]
    // Output: true
```

#### Поиск всех элементов согласно условию
```groovy
  def map = [1:20, a:30, 2:42]
// Возвращаемый тип данных java.util.ArrayList, в отличие от findAll, где возвращается class java.util.LinkedHashMap
  println map.grep{it.value > 20}.getClass()
    // Output: class java.util.ArrayList
```

#### Проверка истинности условия для всех перебираемых элементов Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
  println map.every{it.key instanceof Integer}
    // Output: false
  println map.every{it.value instanceof Integer}
    // Output: true
```

#### Проверка истинности условия для одного элемента в перебираемой Map
```groovy
  def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
  println map.any{it.key instanceof String}
    // Output: true
  println map.any{it.value instanceof Boolean}
    // Output: false
```

#### Преобразование коллекции collect
```groovy
  def map = [
    1:[name:"Jerry", age:42, city:"New York"],
    2:[name:"Long", age:25, city:"New York"],
    3:[name:"Dustin", age:29, city:"New York"],
    4:[name:"Dustin", age:34, city:"New York"]]
// Возвращаемый тип данных java.util.ArrayList
  def newMap = map.collect{it.value.name}
  println map
    // Output: [1:[name:Jerry, age:42, city:New York], 2:[name:Long, age:25, city:New York], 3:[name:Dustin, age:29, city:New York], 4:[name:Dustin, age:34, city:New York]]
  println newMap
    // Output: [Jerry, Long, Dustin, Dustin]
```

#### Преобразование коллекции collectEntries
```groovy
  def map = [
    1:[name:"Jerry", age:42, city:"New York"],
    2:[name:"Long", age:25, city:"New York"],
    3:[name:"Dustin", age:29, city:"New York"],
    4:[name:"Dustin", age:34, city:"New York"]]
// Возвращаемый тип данных java.util.LinkedHashMap
  def newMap = map.collectEntries{key, value -> [key, value.name]}
  println map
    // Output: [1:[name:Jerry, age:42, city:New York], 2:[name:Long, age:25, city:New York], 3:[name:Dustin, age:29, city:New York], 4:[name:Dustin, age:34, city:New York]]
  println newMap
    // Output: [1:Jerry, 2:Long, 3:Dustin, 4:Dustin]
```

#### Создание новой коллекции с группировкой по условию
```groovy
  def map = [1:20, 2:40, 3:11, 4:93]
  println map.groupBy{it.value > 19}
    // Output: [true:[1:20, 2:40, 4:93], false:[3:11]]
```

#### Создание новой коллекции с указанием диапазона выборки
```groovy
  def map = [1:20, 2:40, 3:11, 4:93]
  println map.subMap([1,2])
    // Output: [1:20, 2:40]
```

#### Сортировка
```groovy
  def map = [ab:20, a:40, cb:11, ba:93]
  println map.sort()
    // Output: [a:40, ab:20, ba:93, cb:11]
```

#### Сортировка по условию для ключа
```groovy
  def map = [ab:20, a:40, cb:11, ba:93]
  def compSortedMap = map.sort({k1, k2 -> k1 <=> k2} as Comparator)
    // Output: [a:40, ab:20, ba:93, cb:11]
```

#### Сортировка по условию для значения
```groovy
  def map = [ab:20, a:40, cb:11, ba:93]
  def cloSortedMap = map.sort({it1, it2 -> it1.value <=> it1.value})
    // Output: [cb:11, ab:20, a:40, ba:93]
```

#### Ссылки на ресурсы
* [docs.groovy-lang.org](https://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html)
* [www.baeldung.com](https://www.baeldung.com/groovy-maps)
* [groovy-gpath-in-rest-assured-part1-overview](https://www.james-willett.com/groovy-gpath-in-rest-assured-part1-overview/)
* [rest-assured-gpath-json](https://www.james-willett.com/rest-assured-gpath-json/)
* [www.tutorialspoint.com](https://www.tutorialspoint.com/groovy/index.htm)
* [https://ru.wikibooks.org/wiki/Groovy](https://ru.wikibooks.org/wiki/Groovy)
* [https://www.james-willett.com/groovy-gpath-in-rest-assured-part1-overview/](https://www.james-willett.com/groovy-gpath-in-rest-assured-part1-overview/)
* [https://www.james-willett.com/rest-assured-gpath-json/](https://www.james-willett.com/rest-assured-gpath-json/)